#include "drv_touch_port.h"
#include <rtthread.h>
#include <rtdevice.h>

TOUCH CT_TOUCH;
//控制I2C速度的延时
//void rt_hw_us_delay(rt_uint32_t us)
//{
//    rt_uint32_t delta;
//    /* 获得延时经过的 tick 数 */
//    us = us * (SysTick->LOAD/(1000000/RT_TICK_PER_SECOND));
//    /* 获得当前时间 */
//    delta = SysTick->VAL;
//    /* 循环获得当前时间，直到达到指定的时间后退出循环 */
//    while (delta - SysTick->VAL< us);
//}
void CT_Delay(void)
{
	rt_hw_us_delay(2);
} 
//电容触摸芯片IIC接口初始化
void CT_IIC_Init(void)
{					     
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_GPIOB_CLK_ENABLE();						//开启GPIOH时钟
    
    GPIO_Initure.Pin=GPIO_PIN_8;            //PH6
    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出
    GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
    HAL_GPIO_Init(GPIOB,&GPIO_Initure);     //初始化
	
    GPIO_Initure.Pin=GPIO_PIN_9;            //PI3
    HAL_GPIO_Init(GPIOB,&GPIO_Initure);     //初始化
    CT_IIC_SDA_H;	  	  
		CT_IIC_SCL_H;
}
//产生IIC起始信号
void CT_IIC_Start(void)
{
	CT_SDA_OUT();     //sda线输出
	CT_IIC_SDA_H;	  	  
	CT_IIC_SCL_H;
	rt_hw_us_delay(30);
 	CT_IIC_SDA_L;//START:when CLK is high,DATA change form high to low 
	CT_Delay();
	CT_IIC_SCL_L;//钳住I2C总线，准备发送或接收数据 
}	  
//产生IIC停止信号
void CT_IIC_Stop(void)
{
	CT_SDA_OUT();//sda线输出
	CT_IIC_SCL_L; 
	CT_IIC_SDA_L;//STOP:when CLK is high DATA change form low to high
	rt_hw_us_delay(30);
	CT_IIC_SCL_H; 
	CT_Delay(); 
	CT_IIC_SDA_H;//发送I2C总线结束信号  
}
//等待应答信号到来
//返回值：1，接收应答失败
//        0，接收应答成功
rt_uint8_t CT_IIC_Wait_Ack(void)
{
	rt_uint8_t ucErrTime=0;
	CT_SDA_IN();      //SDA设置为输入  
	CT_IIC_SDA_H;	   
	CT_IIC_SCL_H;
	CT_Delay();
	while(CT_READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			CT_IIC_Stop();
			return 1;
		} 
		CT_Delay();
	}
	CT_IIC_SCL_L;//时钟输出0 	   
	return 0;  
} 
//产生ACK应答
void CT_IIC_Ack(void)
{
	CT_IIC_SCL_L;
	CT_SDA_OUT(); 
	CT_IIC_SDA_L;
	CT_Delay();
	CT_IIC_SCL_H;
	CT_Delay();
	CT_IIC_SCL_L;
}
//不产生ACK应答		    
void CT_IIC_NAck(void)
{
	CT_IIC_SCL_L;
	CT_SDA_OUT(); 
	CT_IIC_SDA_H;
	CT_Delay();
	CT_IIC_SCL_H;
	CT_Delay();
	CT_IIC_SCL_L;
}					 				 				     
//IIC发送一个字节
//返回从机有无应答
//1，有应答
//0，无应答			  
void CT_IIC_Send_Byte(rt_uint8_t txd)
{                        
   rt_uint8_t t;   
	 CT_SDA_OUT(); 	    
   CT_IIC_SCL_L;//拉低时钟开始数据传输
	 CT_Delay();
	 for(t=0;t<8;t++)
    { 
			if((txd&0x80)>>7)
			{
				CT_IIC_SDA_H;
			}
			else
			{
				CT_IIC_SDA_L;
			}
			txd<<=1; 	
			CT_Delay();        
			CT_IIC_SCL_H; 
			CT_Delay();
			CT_IIC_SCL_L;	
			CT_Delay();
    }	 
} 	    
//读1个字节，ack=1时，发送ACK，ack=0，发送nACK   
rt_uint8_t CT_IIC_Read_Byte(unsigned char ack)
{
	rt_uint8_t i,receive=0;
 	CT_SDA_IN();//SDA设置为输入
	rt_hw_us_delay(30);
	for(i=0;i<8;i++ )
	{ 
		CT_IIC_SCL_L; 	    	   
		CT_Delay();
		CT_IIC_SCL_H;	 
		receive<<=1;
		if(CT_READ_SDA)receive++;   
        CT_Delay(); 
	}	  				 
	if (!ack)CT_IIC_NAck();//发送nACK
	else CT_IIC_Ack(); //发送ACK   
 	return receive;
}
//向FT5206写入一次数据
//reg:起始寄存器地址
//buf:数据缓缓存区
//len:写数据长度
//返回值:0,成功;1,失败.
rt_uint8_t FT5206_WR_Reg(rt_uint16_t reg,rt_uint8_t *buf,rt_uint8_t len)
{
	rt_uint8_t i;
	rt_uint8_t ret=0;
	CT_IIC_Start();	 
	CT_IIC_Send_Byte(FT_CMD_WR);	//发送写命令 	 
	CT_IIC_Wait_Ack(); 	 										  		   
	CT_IIC_Send_Byte(reg&0XFF);   	//发送低8位地址
	CT_IIC_Wait_Ack();  
	for(i=0;i<len;i++)
	{	   
    	CT_IIC_Send_Byte(buf[i]);  	//发数据
		ret=CT_IIC_Wait_Ack();
		if(ret)break;  
	}
    CT_IIC_Stop();					//产生一个停止条件	    
	return ret; 
}
//从FT5206读出一次数据
//reg:起始寄存器地址
//buf:数据缓缓存区
//len:读数据长度			  
void FT5206_RD_Reg(rt_uint16_t reg,rt_uint8_t *buf,rt_uint8_t len)
{
	rt_uint8_t i; 
 	CT_IIC_Start();	
 	CT_IIC_Send_Byte(FT_CMD_WR);   	//发送写命令 	 
	CT_IIC_Wait_Ack(); 	 										  		   
 	CT_IIC_Send_Byte(reg&0XFF);   	//发送低8位地址
	CT_IIC_Wait_Ack();  
 	CT_IIC_Start();  	 	   
	CT_IIC_Send_Byte(FT_CMD_RD);   	//发送读命令		   
	CT_IIC_Wait_Ack();	   
	for(i=0;i<len;i++)
	{	   
    	buf[i]=CT_IIC_Read_Byte(i==(len-1)?0:1); //发数据	  
	} 
    CT_IIC_Stop();//产生一个停止条件     
} 

//初始化FT5206触摸屏
//返回值:0,初始化成功;1,初始化失败 
rt_uint8_t FT5206_Init(void)
{
	rt_uint8_t temp[2]; 
    GPIO_InitTypeDef GPIO_Initure;
 
    __HAL_RCC_GPIOA_CLK_ENABLE();			//开启GPIOH时钟
    __HAL_RCC_GPIOC_CLK_ENABLE();			//开启GPIOI时钟
                
    //PA4
    GPIO_Initure.Pin=GPIO_PIN_4;            //PG10
    GPIO_Initure.Mode=GPIO_MODE_INPUT;      //输入
    GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
    HAL_GPIO_Init(GPIOA,&GPIO_Initure);     //初始化
            
    //PC9
    GPIO_Initure.Pin=GPIO_PIN_9;            //PI8
    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出
    HAL_GPIO_Init(GPIOC,&GPIO_Initure);     //初始化
        
	CT_IIC_Init();      	//初始化电容屏的I2C总线  
	CT_RST_L;				//复位
	rt_thread_delay(20);
 	CT_RST_H;				//释放复位		    
	rt_thread_delay(50);  	
	temp[0]=0;
	FT5206_WR_Reg(FT_DEVIDE_MODE,temp,1);	//进入正常操作模式 
	FT5206_WR_Reg(FT_ID_G_MODE,temp,1);		//查询模式 
	temp[0]=22;								//触摸有效值，22，越小越灵敏	
	FT5206_WR_Reg(FT_ID_G_THGROUP,temp,1);	//设置触摸有效值
	temp[0]=12;								//激活周期，不能小于12，最大14
	FT5206_WR_Reg(FT_ID_G_PERIODACTIVE,temp,1); 
	//读取版本号，参考值：0x3003
	FT5206_RD_Reg(FT_ID_G_LIB_VERSION,&temp[0],2);  
	if((temp[0]==0X30&&temp[1]==0X03)||temp[1]==0X01||temp[1]==0X02)//版本:0X3003/0X0001/0X0002
	{
		//rt_kprintf("CTP ID:%x\r\n",((rt_uint16_t)temp[0]<<8)+temp[1]);
		return 0;
	} 
	return 1;
}

const rt_uint16_t FT5206_TPX_TBL[5]={FT_TP1_REG,FT_TP2_REG,FT_TP3_REG,FT_TP4_REG,FT_TP5_REG};
//扫描触摸屏(采用查询方式)
//mode:0,正常扫描.
//返回值:当前触屏状态.
//0,触屏无触摸;1,触屏有触摸
rt_uint8_t sta = 0;
rt_uint8_t FT5206_Scan(rt_uint8_t mode)
{
	rt_uint8_t buf[4];
	rt_uint8_t i=0;
	rt_uint8_t res=0;
	rt_uint8_t temp;
	
	rt_uint8_t touchtype = 1;
	//static rt_uint8_t t=0;//控制查询间隔,从而降低CPU占用率   
	//t++;
	//if((t%5)==0||t<50)//空闲时,每进入10次CTP_Scan函数才检测1次,从而节省CPU使用率
	{
		FT5206_RD_Reg(FT_REG_NUM_FINGER,&mode,1);//读取触摸点的状态  
		if((mode&0XF)&&((mode&0XF)<6))
		{
			temp=0XFF<<(mode&0XF);//将点的个数转换为1的位数,匹配tp_dev.sta定义 
			sta=(~temp)|TP_PRES_DOWN|TP_CATH_PRES; 
			for(i=0;i<5;i++)
			{
				if(sta&(1<<i))		//触摸有效?
				{
					FT5206_RD_Reg(FT5206_TPX_TBL[i],buf,4);	//读取XY坐标值 
					if(touchtype&0X01)//横屏
					{
						CT_TOUCH.y[i]=((rt_uint16_t)(buf[0]&0X0F)<<8)+buf[1];
						CT_TOUCH.x[i]=((rt_uint16_t)(buf[2]&0X0F)<<8)+buf[3];
					}
					//else
//					{
//						tp_dev.x[i]=lcddev.width-(((rt_uint16_t)(buf[0]&0X0F)<<8)+buf[1]);
//						tp_dev.y[i]=((rt_uint16_t)(buf[2]&0X0F)<<8)+buf[3];
//					}  
					if((buf[0]&0XF0)!=0X80)CT_TOUCH.x[i]=CT_TOUCH.y[i]=0;//必须是contact事件，才认为有效
					//rt_kprintf("x[%d]:%d,y[%d]:%d\r\n",i,tp_dev.x[i],i,tp_dev.y[i]);
				}			
			} 
			res=1;
			if(CT_TOUCH.x[0]==0 && CT_TOUCH.y[0]==0)mode=0;	//读到的数据都是0,则忽略此次数据
			//t=0;		//触发一次,则会最少连续监测10次,从而提高命中率
		}
	}
	if((mode&0X1F)==0)//无触摸点按下
	{ 
		if(sta&TP_PRES_DOWN)	//之前是被按下的
		{
			sta&=~(1<<7);	//标记按键松开
		}else						//之前就没有被按下
		{ 
			CT_TOUCH.x[0]=0xffff;
			CT_TOUCH.y[0]=0xffff;
			sta&=0XE0;	//清除点有效标记	
		}	 
	} 	
	//if(t>240)t=5;//重新从10开始计数
	return res;
}
